/*
 * © Copyright 2011 Romain Marteau, Matthieu Totet
 * 
 *    This file is part of VineaToum.
 *
 *    VineaToum is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    VineaToum is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with VineaToum.  If not, see <http://www.gnu.org/licenses/>.
 *    
 */

package org.vineatoum.view.utils.jtablecustom;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.EventObject;
import java.util.List;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JInternalFrame;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.JButton;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class JTableCustom<T extends TableListener> extends JTable {
	private static final long serialVersionUID = 3441143160875038600L;
	
	private CutomTableModel<T> model;
	private TableRowSorter<TableModel> sorter;

	@SuppressWarnings("unused")
	private JTableCustom() {
		
	}
	
	public JTableCustom(TableListener instance) {
		super();
		setBorder(null);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		model = new CutomTableModel<T>(instance);
		
		addMouseListener(new JTableButtonMouseListener(this));

		getTableHeader().setBackground(Color.LIGHT_GRAY);
		
		this.setModel(model);
		this.setDefaultRenderer(Object.class, new DefaultTableCellRendererCustom());
		this.setDefaultRenderer(JButton.class, new JTableButtonRenderer());
		
		TableColumn col = getColumnModel().getColumn(getColumnCount() - 1);
		col.setMaxWidth(16);

		addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void keyReleased(KeyEvent arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyChar() == KeyEvent.VK_ENTER) {
					System.out.println("out");
				} else {
					System.out.println("rien");
//					e.setSource(getRootPane());
//					getRootPane().);
//					dispatchEvent(e);

//					e.consume();					
				}
			}
		});

		addFocusListener(new FocusListener() {
			
			@Override
			public void focusLost(FocusEvent arg0) {				
				getSelectionModel().removeSelectionInterval(getSelectionModel().getMinSelectionIndex(), getSelectionModel().getMaxSelectionIndex());
			}
			
			@Override
			public void focusGained(FocusEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		Action actions = new AbstractAction() {
			private static final long serialVersionUID = 6496962086856031807L;

			public void actionPerformed(ActionEvent ae) {
				if (isEditing()) {
					getCellEditor().stopCellEditing();
				} else {
					editCellAt(getSelectedRow(), getSelectedColumn());
				}
			}
		};
		
		getInputMap(JInternalFrame.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
				KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "SOME_ACTION");
		getInputMap(JInternalFrame.WHEN_FOCUSED).put(
				KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "SOME_ACTION");

		getActionMap().put("SOME_ACTION", actions);
		
		setDefaultEditor(new Object().getClass(), new JTableCustomEditor());
//		getDefaultEditor(new Object().getClass()).addCellEditorListener(new CellEditorListener() {
//			
//			@Override
//			public void editingStopped(ChangeEvent e) {
//				
//			}
//			
//			@Override
//			public void editingCanceled(ChangeEvent e) {
//				// TODO Auto-generated method stub
//				
//			}
//		});
		putClientProperty("terminateEditOnFocusLost", true); 
		
		sorter = new TableRowSorter<TableModel>(getModel());
	    setRowSorter(sorter);
	}
	
	public TableRowSorter<TableModel> getSorter() {
		return sorter;
	}

	@Override
	public boolean isCellEditable(int row, int column) {
		if (this.getRowCount() - 1 == row
				|| this.getColumnCount() - 1 == column) {
			return false;
		} else {
			return true;
		}
	}

	@Override
	public boolean isCellSelected(int row, int column) {
		if (this.getRowCount() - 1 == row
				|| this.getColumnCount() - 1 == column) {
			return false;
		} else {
			return super.isCellSelected(row, column);
		}
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		if (columnIndex == getColumnCount() - 1)
			return JButton.class;
		else
			return super.getColumnClass(columnIndex);
	}

	@Override
	public boolean editCellAt(int row, int column, EventObject e) {
		boolean edit = super.editCellAt(row, column, e);
		if (edit) {
			return fireEditingStarted(this, row, column);
		} else {
			return false;
		}

	}

	protected boolean fireEditingStarted(JTableCustom<T> table, int row, int column) {
		return true;
		// FIXME We have to return false when we override the function and stop
		// the cell editing.
		// Certainly better to do. Add a parameter/flag to indicate if the
		// edition mode is basic ?
	}
	
	@Override
	public CutomTableModel<T> getModel() {
		return model;
	}

	public TableListener getValueAt(int row) {
		return model.rows.get(convertRowIndexToModel(row));
	}
	
	public void addRow(T row, int i) {
		model.insertRow(i, row);
	}
	
	public void addRow(T row) {
		model.insertRow(row);
	}

	public Vector<T> getData() {
		return model.getData();
	}

	public void setData(List<T> data) {
		model.setData(data);
	}
	
    @Override
    public int getRowCount() {
        // fake an additional row
        return super.getRowCount() + 1;
    }
    
    @Override
    public Object getValueAt(final int row, int column) { //FIXME
        if(row < super.getRowCount()) {
            return super.getValueAt(row, column);
        } else if (column == getColumnCount() - 1) {
			final JButton button = new JButton(new ImageIcon(getClass().getResource("/img/add.png")));
			button.addActionListener(new ActionListener() {
				@SuppressWarnings("unchecked")
				public void actionPerformed(ActionEvent action) {
					model.insertRow(row, (T) model.instance.getNewInstance());
				}
			});
			return button;
        } else {
        	return "";
        }
    }

    @Override
    public int convertRowIndexToModel(int viewRowIndex) {
        if(viewRowIndex < super.getRowCount()) {
            return super.convertRowIndexToModel(viewRowIndex);
        }
        return super.getRowCount(); // can't convert our faked row
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        if(row < super.getRowCount()) {
            super.setValueAt(aValue, row, column);
        } else {
            Object[] rowData = new Object[getColumnCount()];
            Arrays.fill(rowData, "");
            rowData[convertColumnIndexToModel(column)] = aValue;
            // That's where we insert the new row.
            // Change this to work with your model.
            ((DefaultTableModel)getModel()).addRow(rowData);
        }
    }

	public void setValueAt(T analyseLaboPanel, int row) {
		model.setValueAt(analyseLaboPanel, row);
	}


}
